package com.golte.utils;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 
 * @version V1.0
 *  
 * @description: RSA签名
 *
 * @author hegd
 * 
 * @date 2021-06-03
 * 
 */

public class RSAUtils {


    /**
     * 签名算法
     */
    public final String SIGNATURE_INSTANCE = "SHA1WithRSA";

    /**
     * RSA私钥Key
     */
    private String privateKey;

    /**
     * RSA公钥Key
     */
    private String publicKey;


    public RSAUtils(String privateKey, String publicKey) {
        this.privateKey = privateKey;
        this.publicKey = publicKey;

    }

    public RSAUtils(){

    }



    /**
     * 生成密钥对
     *
     * @return
     * @throws Exception
     */
    public KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 公钥字符串转PublicKey实例
     *
     * @param publicKey
     * @return
     * @throws Exception
     */
    public PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 私钥字符串转PrivateKey实例
     *
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 公钥加密
     *
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public byte[] encryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    public byte[] encryptByPublicKey(byte[] content) throws Exception {
        return encryptByPublicKey(content, getPublicKey(publicKey));
    }

    public String encryptByPublicKey(String content, String publicKey) throws Exception {
        return new String(Base64.getEncoder().encode(encryptByPublicKey(content.getBytes(StandardCharsets.UTF_8), getPublicKey(publicKey))));

    }

    public String encryptByPublicKey(String content) throws Exception {
        return new String(Base64.getEncoder().encode(encryptByPublicKey(content.getBytes(StandardCharsets.UTF_8))));
    }

    /**
     * 私钥解密
     *
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    public byte[] decryptByPrivateKey(byte[] content) throws Exception {
        return decryptByPrivateKey(content, getPrivateKey(privateKey));
    }

    public static String decryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(decryptByPrivateKey(Base64.getDecoder().decode(content), getPrivateKey(privateKey)), StandardCharsets.UTF_8);

    }

    public String decryptByPrivateKey(String content) throws Exception {
        return new String(decryptByPrivateKey(Base64.getDecoder().decode(content)), StandardCharsets.UTF_8);
    }

    /**
     * 私钥加密
     *
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public byte[] encryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    public byte[] encryptByPrivateKey(byte[] content) throws Exception {
        return encryptByPrivateKey(content, getPrivateKey(privateKey));
    }

    public String encryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(encryptByPrivateKey(content.getBytes(StandardCharsets.UTF_8), getPrivateKey(privateKey)), StandardCharsets.UTF_8);
    }

    public String encryptByPrivateKey(String content) throws Exception {
        return new String(encryptByPrivateKey(content.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
    }

    /**
     * 公钥解密
     *
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public byte[] decrypByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    public byte[] decrypByPublicKey(byte[] content) throws Exception {
        return decrypByPublicKey(content, getPublicKey(publicKey));
    }

    public String decrypByPublicKey(String content, String publicKey) throws Exception {
        return new String(decrypByPublicKey(Base64.getDecoder().decode(content), getPublicKey(publicKey)), StandardCharsets.UTF_8);

    }

    public String decrypByPublicKey(String content) throws Exception {
        return new String(decrypByPublicKey(Base64.getDecoder().decode(content)), StandardCharsets.UTF_8);
    }

    /**
     * 签名
     *
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public byte[] sign(byte[] content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initSign(privateKey);
        signature.update(content);
        return signature.sign();
    }

    public byte[] sign(byte[] content) throws Exception {
        return sign(content, getPrivateKey(privateKey));
    }

    public String sign(String content, String privateKey) throws Exception {
        return new String(Base64.getEncoder().encode(sign(content.getBytes(StandardCharsets.UTF_8), getPrivateKey(privateKey))), StandardCharsets.UTF_8);
    }

    public String sign(String content) throws Exception {
        return new String(Base64.getEncoder().encode(sign(content.getBytes(StandardCharsets.UTF_8))), StandardCharsets.UTF_8);
    }

    /**
     * 验签
     *
     * @param content
     * @param sign
     * @param publicKey
     * @return
     * @throws Exception
     */
    public boolean verify(byte[] content, byte[] sign, PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(sign);
    }

    public boolean verify(byte[] content, byte[] sign) throws Exception {
        return verify(content, sign, getPublicKey(publicKey));
    }

    public boolean verify(String content, String sign, String publicKey) throws Exception {
        return verify(content.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(sign), getPublicKey(publicKey));
    }

    public boolean verify(String content, String sign) throws Exception {
        return verify(content.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(sign), getPublicKey(publicKey));
    }

    public static void main(String[] args) {
        try {
            String publicKeyS = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2uI9w6r9uBB5QUow/L9PVBpBYuPjx6ZJvayq37Kgr3hdY/gLqmLDHHpiUBinZTtxeSc1UH+oLBZgcjnjNH0FEZBAAHSD8A+m2J2TRftosOdRxGfJPD1BImQhfT5jgJjp2q8qlWMYTC64b/zgCV9e1ueT1ZikPBnIPN9OQliR5RwIDAQAB";
            String privateKeyS = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALa4j3Dqv24EHlBSjD8v09UGkFi4+PHpkm9rKrfsqCveF1j+AuqYsMcemJQGKdlO3F5JzVQf6gsFmByOeM0fQURkEAAdIPwD6bYnZNF+2iw51HEZ8k8PUEiZCF9PmOAmOnaryqVYxhMLrhv/OAJX17W55PVmKQ8Gcg8305CWJHlHAgMBAAECgYEAkRcsj7VYHLwYdh+WTfZkdxunM0xuIWofZWnrmfDJ+Ut5rqjFGBP3C6Y38hKS2IPOaPChotNUvTvL9aEMO5U99QD6iFzJTh9qS9uRC1qumnnXKZaVKHv7OE0Tr3UgSKB/0MQ01GWx2MADExYn+JK4SDkAVH29w4p1y8bCsxzeJMECQQDfGdc+zI6H1B+WRnfGoA6e6P6vlZKydsti/zcirSwyywdx47N7ZVpY1nA+LZSHFAndI3dQ46Ai+9pl2XgMmXZtAkEA0apbSOSlo8px0gdzmLHOYfdGlfkYXhc3CnNuQvXeDmQOCl+4ZR6dJDQZWZApSU1vuPriK7Et1a5fp5mM6QKuAwJBAJunT8GEvjyOBqu15oMx0IGWVXrzhDH3J9ed8D3FTHzzofIXx3VkNTCeDBmVe3byyB79S5Wn+mXuCWXd4CAKQdECQQC9OqDKyDpK+rMBmWIWRRv8xR16y+fXO+KcVxQD8T3qBRm6+StGcHvpKfBbKkZo9y/HZv9r6axxd8CzVl2cC6QbAkByti+KllDxhGV8ORQ2+EXlefu9E4mzmX6r8JRSCnW6X/8ROphKR6AP12+edN3jaZt5iLVnEMc16CWnjL0mXCs3";
            RSAUtils rsaUtils = new RSAUtils(privateKeyS, publicKeyS);
//            PublicKey publicKey = keyPair.getPublic();
//            PrivateKey privateKey = keyPair.getPrivate();
//            System.out.println(new String(Base64.getEncoder().encode(publicKey.getEncoded())));
//            System.out.println(new String(Base64.getEncoder().encode(privateKey.getEncoded())));
//            String value = "5";
//            String sign = RSAUtils.sign(value);
//            System.out.println(sign);
//            System.out.println(RSAUtils.verify(value, sign));
            String encryptByPublicKey = rsaUtils.encryptByPublicKey("TPJK2021@qaz", publicKeyS);
//            String encryptByPrivateKey = rsaUtils.encryptByPrivateKey("1111", privateKeyS);
//            String decryptByPrivateKey = rsaUtils.decryptByPrivateKey("rxbQiIW+0XW8C8T0wk5mAOFkpSRvgUmqf7HDHUu5dwOiMVwpv0+TI+Nu8tiknhQXlEF53ZZNKXefStUlP7GUTyl6Dpz3zG0YMQRq3A4fZg9eN45shvgH43iQTpjk8jjhoBMATbzlhtQVsQncbr/AZ+QSAGioA/QN/OnfeRMi2CM=");
            System.out.println("公钥加密:" + encryptByPublicKey);
//            System.out.println("私钥加密:" + encryptByPrivateKey);
//            System.out.println("私钥解密:" + decryptByPrivateKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
